package com.wf.service;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.wf.context.BaseContext;
import com.wf.domain.ContractInfo;
import com.wf.dto.ContractDTO;
import com.wf.dto.ContractMap;
import com.wf.dto.TaskDTO;
import com.wf.exception.ApartmentException;
import com.wf.utils.AliOssUtil;
import com.wf.utils.RedisUtil;
import com.wf.utils.WordUtils;
import com.wf.vo.TaskRepresentationVO;
import com.wf.vo.TaskVO;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.FileNotFoundException;
import java.time.LocalDate;
import java.util.*;

import static com.wf.constant.RedisConstant.APARTMENT_SIGN_APPLY;


/**
 * @author mpk
 * @since 2024/9/16 11:56:58
 */
@Service
public class AgencyService {

    @Autowired
    AliOssUtil aliOssUtil;
    @Autowired
    ContractInfoService contractInfoService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    RedisUtil redisUtil;

    /**
     * 启动合同审批流程
     *
     * @param contractDTO 合同数据传输对象，包含租赁相关信息
     * @throws ApartmentException 如果合同生成失败，抛出此异常
     */
    @DSTransactional
    public void startAgencyProcess(ContractDTO contractDTO) throws ApartmentException {

        if(!Validator.isMobile(contractDTO.getTenantPhone()))
        {
            throw new ApartmentException("租户手机号格式不正确!");
        }
        if(StrUtil.isEmpty(contractDTO.getTenantName())&&StrUtil.isEmpty(contractDTO.getTenantIdCard()))
        {
            throw new ApartmentException("租户姓名和身份证号不能为空");
        }

        Set set = redisUtil.sGet(APARTMENT_SIGN_APPLY);
        if(set.contains(contractDTO.getContractId()))
        {
            throw new ApartmentException("合同正在审批中，请勿重复提交");
        }

        // 获取合同的起始和结束日期
        String startDate = contractDTO.getStartDate();
        String endDate = contractDTO.getEndDate();

        // 解析日期字符串为DateTime对象
        DateTime fromDate = DateUtil.parse(startDate, "yyyy-MM-dd");
        DateTime toDate = DateUtil.parse(endDate, "yyyy-MM-dd");

        // 计算租赁月数
        long month = DateUtil.betweenMonth(fromDate, toDate, true);
        if(month<=0)
        {
           throw new ApartmentException("租赁月份至少一个月！");
        }

        // 设置合同的总租赁期和付款周期
        contractDTO.setTotalLeasePeriod(month + "");
        contractDTO.setPaymentCycle(month + "");

        // 获取合同ID和相关信息
        String contractId = contractDTO.getContractId();
        ContractInfo contractInfo = contractInfoService.getById(contractId);

        // 获取合同编号和合同模板
        String contractNumber = contractInfo.getContractNumber();
        String stencil = contractInfo.getContractStencil();

        // 将模板的文件格式从pdf更改为docx，以便使用Word模板
        stencil = stencil.replace("pdf", "docx");

        // 尝试生成合同文档并启动流程
        try {
            // 构建文件名前缀和输出路径
            String pre = LocalDateTimeUtil.formatNormal(LocalDate.now());
            String outPathWord = "D:\\agency\\" + pre +"\\"+"agency\\"+ contractNumber + ".docx";
            String outPathPDF = "D:\\agency\\" + pre +"\\"+"agency\\"+ contractNumber + ".pdf";

            // 创建合同映射对象
            ContractMap map = new ContractMap(contractDTO);

            // 使用HTTP方式编译Word文档
            WordUtils.compileHttp(stencil, outPathWord, map);

            // 将Word文档转换为PDF
            WordUtils.convertToPDF(outPathWord, outPathPDF);

            // 读取Word和PDF文件的字节内容
            byte[] wordBytes = FileUtil.readBytes(outPathWord);
            byte[] pdfBytes = FileUtil.readBytes(outPathPDF);

            // 将文件上传到阿里云OSS
            String word = aliOssUtil.upload(wordBytes, pre + "/"+"agency/"+contractNumber + ".docx");
            String pdf = aliOssUtil.upload(pdfBytes, pre + "/"+"agency/"+contractNumber + ".pdf");

            // 创建包含文件链接和租赁月数的映射
            HashMap<String, Object> hashMap = new HashMap<>();
            ContractInfo update = new ContractInfo();
            update.setUserId(BaseContext.getCurrentId());
            update.setContractId(Integer.valueOf(contractDTO.getContractId()));
            update.setStartTime(LocalDateTimeUtil.parseDate(contractDTO.getStartDate()));
            update.setEndTime(LocalDateTimeUtil.parseDate(contractDTO.getEndDate()));
            update.setContractStencil(pdf);
            hashMap.put("contractInfo", update);
            hashMap.put("month", month);
            hashMap.put("contractNumber",contractNumber);
            hashMap.put("recipientName", contractDTO.getTenantName());

            // 启动流程实例
            ProcessInstance process = runtimeService
                    .startProcessInstanceByKey("agencyProcess", hashMap);

            // 查询任务
            Task task = taskService.createTaskQuery()
                    .processInstanceId(process.getId())
                    .singleResult();

            // 设置任务的执行人
            taskService.setAssignee(task.getId(),  "admin");
            long l = redisUtil.sSet(APARTMENT_SIGN_APPLY, contractDTO.getContractId());


        } catch (Exception e) {
            e.printStackTrace();
            // 如果合同生成失败，抛出异常
            if(e instanceof FileNotFoundException)
            {
                throw new ApartmentException("合同模板文件不存在");
            }
            throw new ApartmentException("合同生成失败");

        }
    }


    public List<TaskVO> getTasks(String assignee) {
        List<Task> tasks = taskService.createTaskQuery().taskAssignee(assignee).list();
        List<TaskVO> taskVOList = new ArrayList<>();
        for (Task task : tasks) {
            TaskVO taskVO = new TaskVO();
            taskVO.setTaskId(task.getId());
            taskVO.setTaskName(task.getName());
            Map<String, Object> variables = taskService.getVariables(task.getId());
            ContractInfo contractInfo =(ContractInfo) variables.get("contractInfo");
            taskVO.setMonth(variables.get("month").toString());
            taskVO.setContractId(contractInfo.getContractId().toString());
            taskVO.setContractNumber(variables.get("contractNumber").toString());
            taskVO.setRecipientName(variables.get("recipientName").toString());
            taskVO.setContractStencil(contractInfo.getContractStencil());
            taskVO.setStartTime(contractInfo.getStartTime());
            taskVO.setEndTime(contractInfo.getEndTime());
            taskVOList.add(taskVO);
        }
        return taskVOList;
    }

    @DSTransactional
    @DS("master")
    public void completeTask(TaskDTO taskDTO) {
        Map<String, Object> variables = taskService.getVariables(taskDTO.getTaskId());
        variables.put("approved", taskDTO.getApproval());
        taskService.complete(taskDTO.getTaskId(), variables);
    }

    public List<HistoricActivityInstance> getHistory(String assignee) {
        return historyService.createHistoricActivityInstanceQuery()
                .taskAssignee(assignee)
                .finished()
                .list();
    }
}
